package wmhsudoku.board;

import java.awt.Point;

public class ErrorMatrix {
	private double error;
	/**
	 * pierwsze 9 indeksów - wiersze
	 * kolejne - kolumny
	 * ostatnie 9 indeksów kwadraty wg. poniższej kolejności:
	 * [1][2][3]
	 * [4][5][6]
	 * [7][8][9]
	 */
	private int[][] errorMatrix = new int[27][9];

	public ErrorMatrix() {
	}

	private int[][] clone2DArray(int[][] array) {
	    int rows=array.length ;

	    //clone the 'shallow' structure of array
	    int[][] newArray =(int[][]) array.clone();
	    //clone the 'deep' structure of array
	    for(int row=0;row<rows;row++){
	        newArray[row]=(int[]) array[row].clone();
	    }

	    return newArray;
	}

	public ErrorMatrix(ErrorMatrix eMatrix) {
		this.error = eMatrix.getError();
		this.errorMatrix = clone2DArray(eMatrix.getErrorMatrix());
	}

	public double getError() {
		return error;
	}

	public int[][] getErrorMatrix() {
		return errorMatrix;
	}

	public void setErrorMatrix(int[][] errorMatrix) {
		this.errorMatrix = errorMatrix;
	}
	
	protected void error() {
		double error = 0.0;
		
		for (int i=0; i<27; ++i) {
			for (int j=0; j<9; ++j) {
				if (errorMatrix[i][j] > 1)
					error += errorMatrix[i][j]-1;
			}
		}
		
		this.error = error;
	}
	
	public void updateErrorMatrix(Point coord, int value, int prevValue) {
		int row = coord.x;
		int column = coord.y;
		
		// row
		if (prevValue > 0)
			--errorMatrix[row][prevValue-1];
		if (value > 0)
			++errorMatrix[row][value-1];
		// column
		if (prevValue > 0)		
			--errorMatrix[column+9][prevValue-1];
		if (value > 0)
			++errorMatrix[column+9][value-1];
		// square
		int sRow = row / 3;
		int sCol = column / 3;
		int square = 18 + sRow*3 + sCol;
		if (prevValue > 0)		
			--errorMatrix[square][prevValue-1];
		if (value > 0)
			++errorMatrix[square][value-1];
	}	
	
	
	public void countAll(Map sudoku) {
		// rows
		for (int i=0; i<9; ++i) {
			countRow(i, sudoku);
		}
		
		// cols
		for (int i=0; i<9; ++i) {
			countColumn(i, sudoku);
		}
		
		// squares
		for (int i=0; i<9; ++i) {
			countSquare(i, sudoku);
		}
		
		error();
	}
	
	
	private void countRow(int index, Map sudoku) {	
		for (int i=1; i<=9; ++i) {
			int count = 0;
			for (int j=0; j<9; ++j) {
				if (sudoku.getField(index, j) == i) {
					++count;
				}
			}
			errorMatrix[index][i-1] = count;
		}
	}
	
	
	private void countColumn(int index, Map sudoku) {
		for (int i=1; i<=9; ++i) {
			int count = 0;
			for (int j=0; j<9; ++j) {
				if (sudoku.getField(j, index) == i) {
					++count;
				}
			}
			errorMatrix[index+9][i-1] = count;
		}
	}

	
	private void countSquare(int index, Map sudoku) {
		int row = (index / 3) * 3;
		int col = (index % 3) * 3;
		for (int k=1; k<=9; ++k) {
			int count = 0;
			for (int i=0; i<3; ++i) {
				for (int j=0; j<3; ++j) {
					if (sudoku.getField(row + i, col + j) == k) {
						++count;
					}
				}
			}
			errorMatrix[index+18][k-1] = count;
		}
	}
}